﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using DCT.Model;

namespace DCT.ViewModel
{
    public class DeviceBaseViewModel : ViewModelBase, IDataErrorInfo
    {
        #region Constructor

        public DeviceBaseViewModel(DeviceBaseModel deviceModel, DeviceBaseGraphModel deviceGraphModel) :
            this(deviceModel, deviceGraphModel, new Point())
        {
        }

        public DeviceBaseViewModel(DeviceBaseModel deviceModel, DeviceBaseGraphModel deviceGraphModel, Point renderTransformOrigin)
        {
            if (deviceModel == null)
                throw new ArgumentNullException("DeviceBaseModel");

            if (deviceGraphModel == null)
                throw new ArgumentNullException("DeviceBaseGraphModel");

            if (renderTransformOrigin == null)
                throw new ArgumentNullException("RenderTransformOrigin");

            _deviceBaseModel = deviceModel;
            _deviceBaseGraphModel = deviceGraphModel;
            _renderTransformOrigin = renderTransformOrigin;
        }

        #endregion // Constructor

        #region Fields

        DeviceBaseModel _deviceBaseModel;
        DeviceBaseGraphModel _deviceBaseGraphModel;
        bool _isSelected;
        bool _isHighLight;
        Point _renderTransformOrigin;
        bool _isPropertyShow;

        #endregion // Fields

        #region Properties

        #region Device Properties

        public DeviceBaseModel DeviceModel
        {
            get
            {
                return _deviceBaseModel;
            }
        }

        public string DeviceID
        {
            get 
            { 
                return string.Format("0x{0:X8}",_deviceBaseModel.DeviceID); 
            }
            //set
            //{
            //    int id = Convert.ToInt32(value, 16);
            //    if (id != _deviceBaseModel.DeviceID)
            //    {
            //        _deviceBaseModel.DeviceID = id;
            //        _deviceBaseGraphModel.DeviceID = id;
            //        base.OnPropertyChanged("DeviceID");
            //    }
            //}
        }

        public DeviceType DeviceType
        {
            get
            {
                try
                {
                    return (DeviceType)Enum.Parse(typeof(DeviceType), _deviceBaseModel.DeviceType);
                }
                catch
                {
                    return DeviceType.Unknow;
                }
            }
        }

        #endregion // Device Properties

        #region DeviceGraph Properties

        public DeviceBaseGraphModel DeviceGraphModel
        {
            get
            {
                return _deviceBaseGraphModel;
            }
        }

        public string DeviceName
        {
            get
            {
                return string.IsNullOrEmpty(_deviceBaseGraphModel.DeviceName) ? this.DeviceID : _deviceBaseGraphModel.DeviceName;
            }
            set
            {
                if (value != _deviceBaseGraphModel.DeviceName)
                {
                    this.InsertUnDoRedoForProperty("DeviceName", value, this.DeviceName);

                    _deviceBaseGraphModel.DeviceName = value;
                    base.OnPropertyChanged("DeviceName");
                }
            }
        }

        public string GraphType
        {
            get
            {
                return _deviceBaseGraphModel.GraphType;
            }
            //set
            //{
            //    if (value != _deviceBaseGraphModel.GraphType)
            //    {
            //        _deviceBaseGraphModel.GraphType = value;
            //        base.OnPropertyChanged("GraphType");
            //    }
            //}
        }

        public virtual Point PositionPoint
        {
            get
            {
                try
                {
                    return Point.Parse(_deviceBaseGraphModel.PositionPoint);
                }
                catch
                {
                    return new Point();
                }
            }
            set
            {
                if (value.ToString() != _deviceBaseGraphModel.PositionPoint)
                {
                    this.InsertUnDoRedoForProperty("PositionPoint", value, this.PositionPoint);

                    _deviceBaseGraphModel.PositionPoint = value.ToString();
                    base.OnPropertyChanged("PositionPoint");
                }                
            }
        }

        public virtual double DeviceWidth
        {
            get
            {
                return _deviceBaseGraphModel.DeviceWidth / 100.0;
            }
            set
            {
                if (value != _deviceBaseGraphModel.DeviceWidth)
                {
                    this.InsertUnDoRedoForProperty("DeviceWidth", value, this.DeviceWidth);

                    _deviceBaseGraphModel.DeviceWidth = Convert.ToInt32(value * 100);
                    base.OnPropertyChanged("DeviceWidth");
                }                
            }
        }

        public virtual double DeviceHeight
        {
            get
            {
                return _deviceBaseGraphModel.DeviceHeight / 100.0;
            }
            set
            {
                if (value != _deviceBaseGraphModel.DeviceHeight)
                {
                    this.InsertUnDoRedoForProperty("DeviceHeight", value, this.DeviceHeight);

                    _deviceBaseGraphModel.DeviceHeight = Convert.ToInt32(value * 100);
                    base.OnPropertyChanged("DeviceHeight");
                }               
            }
        }

        public virtual double DeviceAngle
        {
            get
            {
                return _deviceBaseGraphModel.DeviceAngle / 100.0;
            }
            set
            {
                if (value != _deviceBaseGraphModel.DeviceAngle)
                {
                    this.InsertUnDoRedoForProperty("DeviceAngle", value, this.DeviceAngle);

                    _deviceBaseGraphModel.DeviceAngle = Convert.ToInt32(value * 100);
                    base.OnPropertyChanged("DeviceAngle");
                }               
            }
        }

        #endregion // DeviceGraph Properties

        #region Presentation Properties

        public DeviceMapViewModel DeviceMapViewModel { get; set; }

        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                if (value != _isSelected)
                {
                    _isSelected = value;
                    base.OnPropertyChanged("IsSelected");
                }
            }
        }

        public bool IsHighLight
        {
            get
            {
                return _isHighLight;
            }
            set
            {
                if (value != _isHighLight)
                {
                    _isHighLight = value;
                    base.OnPropertyChanged("IsHighLight");
                }
            }
        }

        public Point RenderTransformOrigin
        {
            get 
            { 
                return _renderTransformOrigin; 
            }
            set
            {
                if (value != _renderTransformOrigin)
                {
                    _renderTransformOrigin = value;
                    base.OnPropertyChanged("RenderTransformOrigin");
                }               
            }
        }

        public bool IsPropertyShow
        {
            get
            {
                return _isPropertyShow;
            }
            set
            {
                if (value != _isPropertyShow)
                {
                    _isPropertyShow = value;

                    base.OnPropertyChanged("IsPropertyShow");
                }
            }
        }

        public virtual bool IsDisplay
        {
            get
            {
                return this.DeviceMapViewModel.DeviceViewModelCollection.Contains(this);
            }
            set
            {
                if (value != this.IsDisplay)
                {
                    if (value)
                    {
                        this.DeviceMapViewModel.DeviceViewModelCollection.Add(this);
                    }
                    else
                    {
                        this.DeviceMapViewModel.DeviceViewModelCollection.Remove(this);
                    }

                    base.OnPropertyChanged("IsDisplay");
                }
            }
        }

        #endregion // Presentation Properties

        #endregion //Properties

        #region Commands

        #region ShowProperty

        public bool ShowProperty_Can()
        {
            return !this.IsPropertyShow;
        }

        public void ShowProperty_Execute()
        {
            this.IsPropertyShow = true;
        }

        RelayCommand _showPropertyCommand;
        public ICommand ShowPropertyCommand
        {
            get
            {
                if (_showPropertyCommand == null)
                    _showPropertyCommand = new RelayCommand(param => this.ShowProperty_Execute(),
                                                        param => this.ShowProperty_Can());

                return _showPropertyCommand;
            }
        }

        #endregion

        #endregion

        #region Methods

        //public DeviceBaseViewModel Clone()
        // {
        //     DeviceBaseViewModel deviceBaseViewModel = (DeviceBaseViewModel)this.MemberwiseClone();
        //     deviceBaseViewModel._deviceBaseModel = deviceBaseViewModel._deviceBaseModel.Clone();
        //     deviceBaseViewModel._deviceBaseGraphModel = deviceBaseViewModel._deviceBaseGraphModel.Clone();
        //     return deviceBaseViewModel;
        // }

        protected void InsertUnDoRedoForProperty(string propertyName, object newValue, object oldValue)
        {
            if (DeviceMapViewModel != null)
            {
                DeviceMapViewModel.UndoRedo.InsertInUnDoRedoForProperty(this, propertyName, newValue, oldValue);
            }
        }

        #endregion //Methods

        #region IDataErrorInfo Members

        string IDataErrorInfo.Error
        {
            get { return (_deviceBaseModel as IDataErrorInfo).Error; }
        }

        string IDataErrorInfo.this[string propertyName]
        {
            get
            {
                string error = null;

                if (propertyName == "CustomerType")
                {
                    // The IsCompany property of the Customer class 
                    // is Boolean, so it has no concept of being in
                    // an "unselected" state.  The CustomerViewModel
                    // class handles this mapping and validation.
                    error = this.ValidateCustomerType();
                }
                else
                {
                    error = (_deviceBaseModel as IDataErrorInfo)[propertyName];
                }

                // Dirty the commands registered with CommandManager,
                // such as our Save command, so that they are queried
                // to see if they can execute now.
                CommandManager.InvalidateRequerySuggested();

                return error;
            }
        }

        string ValidateCustomerType()
        {
            //if (this.CustomerType == Strings.CustomerViewModel_CustomerTypeOption_Company ||
            //   this.CustomerType == Strings.CustomerViewModel_CustomerTypeOption_Person)
            //    return null;

            //return Strings.CustomerViewModel_Error_MissingCustomerType;
            return string.Empty;
        }

        #endregion // IDataErrorInfo Members
    }

    public enum DeviceType
    {
        Axle,
        AxleName,
        Button,
        CBI,
        ControlPoint,      
        DynamicBeacon,
        GradePoint,
        MiscellaneousDevice,
        Path,
        Platform,
        PSD,
        Route,
        Signal,
        StaticBeacon,
        StopPoint,
        Switch,
        Track,
        TrackEnd,
        TrackSegment,
        ZoneController,
        Unknow
    }
}
